/* USER CODE BEGIN Header */
/**
 ******************************************************************************
 * @file           : main.c
 * @brief          : Main program body
 ******************************************************************************
 * @attention
 *
 * Copyright (c) 2022 STMicroelectronics.
 * All rights reserved.
 *
 * This software is licensed under terms that can be found in the LICENSE file
 * in the root directory of this software component.
 * If no LICENSE file comes with this software, it is provided AS-IS.
 *
 ******************************************************************************
 */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "adc.h"
#include "cmsis_gcc.h"
#include "gpio.h"
#include "iwdg.h"
#include "stm32f1xx_hal_iwdg.h"
#include "stm32f1xx_hal_tim.h"
#include "stm32f1xx_hal_uart.h"
#include "tim.h"
#include "usart.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */

#include "tank_power.h"
#include <stdint.h>

/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */

// x
const float INIT_CAMERA_SERVO_1 = 33.5;
// y
const float INIT_CAMERA_SERVO_2 = 41.5;

const float INIT_CAMERA_SERVO_1_MAX = 58;
const float INIT_CAMERA_SERVO_2_MAX = 58;

const float INIT_CAMERA_SERVO_1_MIN = 9;
const float INIT_CAMERA_SERVO_2_MIN = 15;

const float DEFAULT_SERVO_Y_INCREASE_VALUE = 0.8;
const float DEFAULT_SERVO_X_INCREASE_VALUE = 0.8;
float       g_settingYServoIncreaseValue  = 0;
float       g_settingXServoIncreaseValue  = 0;

/**
 * @brief 匹配标准接收头
 */
const unsigned char DATA_BUFFER[4] = {0x04, 0x23, 0x17, 0x32};

/**
 * @brief 接收到的完整的数据
 */
uint8_t receiveDatas[5] = {0x00};

int nowDataIndex = 0;

/**
 * @brief 接收缓存
 */
uint8_t receiveTempData = 0x00;

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

void dataProcess()
{
    switch (receiveDatas[4]) {
        case 0:
            // 复位
            resetServo();
            break;
        case 1:
            // 复位舵机
            reset();
            break;
        case 2:
            // 刹车
            brake();
            break;
        case 3:
            // 停车
            resetPower();
            break;
        case 4:
            // 前进半动力
            setPower(0.5, 0.5);
            break;

        case 5:
            // 前进全动力
            setPower(1, 1);
            break;

        case 6:
            // 后退半动力
            setPower(-0.5, -0.5);
            break;

        case 7:
            // 后退全动力
            setPower(-1, -1);
            break;

        case 8:
            // 左转半动力
            setPower(0, 1);
            break;

        case 9:
            // 左转全动力
            setPower(-1, 1);
            break;
        case 10:
            // 右转半动力
            setPower(1, 0);
            // rotatePower(0, 0.5);
            break;
        case 11:
            // 右转全动力
            setPower(1, -1);
            break;
        case 12:
            // 小步长增加x
            miniIncreaseServoX(0);
            break;
        case 13:
            // 小步长减少x
            miniIncreaseServoX(1);
            break;
        case 14:
            // 小步长增加y
            miniIncreaseServoY(0);
            break;
        case 15:
            // 小步长减少y
            miniIncreaseServoY(1);
            break;

        // -----> Communication Tank Power 
        case 23:
            // 前进全动力
            setPower(0.8, 0.8);
            break;
        case 25:
            // 左转半动力
            setPower(0, 0.5);
            break;
        case 26:
            // 右转半动力
            setPower(0.5, 0);
            break;
        case 22:
            // 右转全动力
            setPower(0.8, -0.8);
            break;
        case 21:
            // 右转全动力
            setPower(-0.8, 0.8);
            break;
        case 27:
            // 左后转
            setPower(0, -0.5);
            break;
        case 28:
            // 右后转
            setPower(-0.5, 0);
            break;
        case 24:
            // 后退
            setPower(-0.8, -0.8);
            break;

        // -----> Communication Camera Servo 
        case 33:
            // 抬头
            miniIncreaseServoY(1);
            break;
        case 35:
            // 抬头x增加
            miniIncreaseServoY(1);
            miniIncreaseServoX(0);
            break;
        case 36:
            // 抬头x减少
            miniIncreaseServoY(1);
            miniIncreaseServoX(1);
            break;
        case 31:
            // x增加
            miniIncreaseServoX(0);
            break;
        case 32:
            // x减少
            miniIncreaseServoX(1);
            break;
        case 37:
            // 低头x减少
            miniIncreaseServoY(0);
            miniIncreaseServoX(0);
            break;
        case 38:
            // 低头x增加
            miniIncreaseServoY(0);
            miniIncreaseServoX(1);
            break;
        case 34:
            // 低头
            miniIncreaseServoY(0);
            break;
        // case 
        default: break;
    }

    __NOP();
}

void HAL_UART_RxCpltCallback(UART_HandleTypeDef* huart)
{
    if (huart == &huart2) {
        if (nowDataIndex < 4) {
            if (nowDataIndex == 0) {
                if (DATA_BUFFER[0] == receiveTempData) {
                    receiveDatas[0] = receiveTempData;
                    nowDataIndex++;
                }
            }
            else {
                if (DATA_BUFFER[nowDataIndex] == receiveTempData) {
                    receiveDatas[nowDataIndex] = receiveTempData;
                    nowDataIndex++;
                }
                else {
                    nowDataIndex = 0;
                }
            }
        }
        else {
            // nowDataIndex++;
            receiveDatas[4] = receiveTempData;
            // if (nowDataIndex == 5) {
            dataProcess();
            nowDataIndex = 0;
            // }
        }

        // HAL_UART_Transmit_IT(&huart2, &receiveTempData, 1);
        HAL_UART_Receive_IT(&huart2, &receiveTempData, 1);
    }
}

/* USER CODE END 0 */

/**
 * @brief  The application entry point.
 * @retval int
 */
int main(void)
{
    /* USER CODE BEGIN 1 */

    /* USER CODE END 1 */

    /* MCU
     * Configuration--------------------------------------------------------*/

    /* Reset of all peripherals, Initializes the Flash interface and the
     * Systick. */
    HAL_Init();

    /* USER CODE BEGIN Init */

    /* USER CODE END Init */

    /* Configure the system clock */
    SystemClock_Config();

    /* USER CODE BEGIN SysInit */

    /* USER CODE END SysInit */

    /* Initialize all configured peripherals */
    MX_GPIO_Init();
    MX_ADC1_Init();
    MX_IWDG_Init();
    MX_TIM1_Init();
    MX_TIM3_Init();
    MX_TIM8_Init();
    MX_USART2_UART_Init();
    /* USER CODE BEGIN 2 */

    g_settingXServoIncreaseValue = DEFAULT_SERVO_X_INCREASE_VALUE;
    g_settingYServoIncreaseValue = DEFAULT_SERVO_Y_INCREASE_VALUE;

    init();

    HAL_UART_Receive_IT(&huart2, &receiveTempData, 1);

    // HAL_UART_Transmit_IT(&huart2, &receiveTempData, 1);

    // setServo(0, 0.5);
    // increaseServo(1, 1);

    // miniIncreaseServoX(0);
    // setServo(-0.5, 0);
    // setPower(0, 0);
    // TIM3->CCR1 = TIM3->ARR * INIT_CAMERA_SERVO_1_MAX / 1000;
    // TIM3->CCR2 = TIM3->ARR * 57 / 1000;

    // y轴
    // 5%
    // TIM3->CCR2 = TIM3->ARR * 5 / 100;D
    // 1.5%
    // y 仰头最大角度
    // TIM3->CCR2 = TIM3->ARR * 15 / 1000;

    // y 俯视最大角度
    // TIM3->CCR2 = TIM3->ARR * 58 / 1000;

    // x 最左
    // TIM3->CCR1 = TIM3->ARR * 58 / 1000;

    // x 最右
    // TIM3->CCR1 = TIM3->ARR * 9 / 1000;

    // TIM3->CCR1 = TIM3->ARR * 33.5 / 1000;
    // TIM3->CCR2 = TIM3->ARR * 41.5 / 1000;
    // HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1);
    // HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_2);

    // TIM8->CCR2 = TIM8->ARR * 50 / 100;
    // TIM8->CCR4 = TIM8->ARR * 50 / 100;

    // HAL_TIM_PWM_Start(&htim8, TIM_CHANNEL_2);
    // HAL_TIM_PWM_Start(&htim8, TIM_CHANNEL_4);

    /* USER CODE END 2 */

    /* Infinite loop */
    /* USER CODE BEGIN WHILE */
    while (1) {
        HAL_IWDG_Refresh(&hiwdg);
        /* USER CODE END WHILE */

        /* USER CODE BEGIN 3 */
    }
    /* USER CODE END 3 */
}

/**
 * @brief System Clock Configuration
 * @retval None
 */
void SystemClock_Config(void)
{
    RCC_OscInitTypeDef       RCC_OscInitStruct = {0};
    RCC_ClkInitTypeDef       RCC_ClkInitStruct = {0};
    RCC_PeriphCLKInitTypeDef PeriphClkInit     = {0};

    /** Initializes the RCC Oscillators according to the specified parameters
     * in the RCC_OscInitTypeDef structure.
     */
    RCC_OscInitStruct.OscillatorType =
        RCC_OSCILLATORTYPE_HSI | RCC_OSCILLATORTYPE_LSI;
    RCC_OscInitStruct.HSIState            = RCC_HSI_ON;
    RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
    RCC_OscInitStruct.LSIState            = RCC_LSI_ON;
    RCC_OscInitStruct.PLL.PLLState        = RCC_PLL_ON;
    RCC_OscInitStruct.PLL.PLLSource       = RCC_PLLSOURCE_HSI_DIV2;
    RCC_OscInitStruct.PLL.PLLMUL          = RCC_PLL_MUL16;
    if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) {
        Error_Handler();
    }

    /** Initializes the CPU, AHB and APB buses clocks
     */
    RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK |
                                  RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
    RCC_ClkInitStruct.SYSCLKSource   = RCC_SYSCLKSOURCE_PLLCLK;
    RCC_ClkInitStruct.AHBCLKDivider  = RCC_SYSCLK_DIV2;
    RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
    RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

    if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK) {
        Error_Handler();
    }
    PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_ADC;
    PeriphClkInit.AdcClockSelection    = RCC_ADCPCLK2_DIV6;
    if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK) {
        Error_Handler();
    }
}

/* USER CODE BEGIN 4 */

/* USER CODE END 4 */

/**
 * @brief  This function is executed in case of error occurrence.
 * @retval None
 */
void Error_Handler(void)
{
    /* USER CODE BEGIN Error_Handler_Debug */
    /* User can add his own implementation to report the HAL error return state
     */
    __disable_irq();
    while (1) {}
    /* USER CODE END Error_Handler_Debug */
}

#ifdef USE_FULL_ASSERT
/**
 * @brief  Reports the name of the source file and the source line number
 *         where the assert_param error has occurred.
 * @param  file: pointer to the source file name
 * @param  line: assert_param error line source number
 * @retval None
 */
void assert_failed(uint8_t* file, uint32_t line)
{
    /* USER CODE BEGIN 6 */
    /* User can add his own implementation to report the file name and line
       number, ex: printf("Wrong parameters value: file %s on line %d\r\n",
       file, line) */
    /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
